home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / zmdm / common.c next >
C/C++ Source or Header  |  1993-06-26  |  29KB  |  1,072 lines

  1. /*
  2.  *                ACKNOWLEDGEMENTS
  3.  *
  4.  *    ZMDM was derived from rz/sz for Unix  posted by 
  5.  *    Chuck Forsberg (...!tektronix!reed!omen!caf ). We
  6.  *    thank him for his excellent code, and for giving
  7.  *    us permission to use and distribute his code and
  8.  *    documentation.
  9.  *
  10.  *    Atari St version by:
  11.  *        Jwahar Bammi
  12.  *            usenet: cwruecmp!bammi@decvax.UUCP
  13.  *            csnet:  bammi@cwru.edu
  14.  *            arpa:   bammi@cwru.edu
  15.  *            CompuServe: 71515,155
  16.  */
  17.  
  18. #define IN_COMMON
  19.  
  20. /*
  21.  * -rev 08-17-86
  22.  * mode function and most of the rest of the system dependent
  23.  * stuff for rb.c and sb.c   This file is #included so the includer
  24.  * can set parameters such as HOWMANY.  See the main file (rz.c/sz.c)
  25.  * for compile instructions.
  26.  */
  27.  
  28. #include "zmdm.h"
  29. #include "zmodem.h"
  30.  
  31. #ifndef Supexec        /* Some versions of osbind don't define Supexec */
  32. #define Supexec(X) xbios(38,X)
  33. #endif
  34.  
  35. #define CRCTABLE
  36.  
  37.         /* GLOBALS */
  38. int Zmodem;        /* ZMODEM protocol requested */
  39. int Nozmodem;    /* If invoked as "rb" */
  40. int Badclose;    /* Error on last close */
  41. int Batch;
  42. int Wcsmask;
  43. int Verbose;
  44. int Quiet;        /* overrides logic that would otherwise set verbose */
  45. int Lleft;        /* number of characters in linbuf */
  46. int Readnum;    /* Number of bytes to ask for in read() from modem */
  47. int Crcflg;
  48. int ForceBinary;        /* local binary force override for rz */
  49.  
  50. FILE *logf;
  51. int vdebug;    /* set if RDEBUG or SDEBUG */
  52.  
  53. char secbuf[KSIZE];
  54. char linbuf[KSIZE];
  55. #ifdef MWC            /* File i/o buffer */
  56. unsigned char *bufr;    /* In MWC it is lmalloc()'ed in main.c */
  57. #else
  58. unsigned char bufr[BBUFSIZ];
  59. #endif
  60. int fout;
  61. int Lastrx;
  62. int Firstsec;
  63. int Eofseen;        /* indicates cpm eof (^Z) has been received */
  64. int errors;
  65. long Bytesleft;        /* number of bytes of incoming file left */
  66. long Modtime;        /* Unix style mod time for incoming file */
  67. int Filemode;        /* Unix style mode for incoming file */
  68. char Pathname[PATHLEN];
  69. char *Progname;        /* the name by which we were called */
  70.  
  71. int Thisbinary;        /* current file is to be received in bin mode */
  72. int Blklen;        /* record length of received packets */
  73. char Lzmanag;        /* Local file management request */
  74. char zconv;        /* ZMODEM file conversion request */
  75. char zmanag;        /* ZMODEM file management request */
  76. char ztrans;        /* ZMODEM file transport request */
  77.  
  78. jmp_buf tohere;        /* For the interrupt on RX timeout */
  79. jmp_buf abrtjmp;    /* for force abort */
  80. jmp_buf busjmp;        /* for bus errors */
  81. jmp_buf addrjmp;    /* for address errors */
  82. unsigned long BusErr, AddrErr;    /* saved vector addresses */
  83. int Zctlesc;        /* Encode control characters */
  84. int SendType;        /* Which send line to use    */
  85. int Modem;        /* Send using Xmodem */
  86. int lsct;
  87. int tryzhdrtype;    /* Header type to send corresponding to Last rx close */
  88. int Txfcs32;        /* TRUE means send binary frames with 32 bit FCS */
  89.  
  90.     /* Globals used by ZMODEM functions */
  91. int Rxframeind;        /* ZBIN or ZHEX indicates type of frame received */
  92. int Rxtype;        /* Type of header received */
  93. int Rxcount;        /* Count of data bytes received */
  94. int Rxtimeout;        /* Tenths of seconds to wait for something */
  95. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  96. char Rxhdr[4];        /* Received header */
  97. char Txhdr[4];        /* Transmitted header */
  98. long Rxpos;        /* Received file position */
  99. long Txpos;        /* Transmitted file position */
  100. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  101.  
  102.         /* Globals used by Sz */
  103. char Lzconv;    /* Local ZMODEM file conversion request */
  104. char Lztrans;
  105. char *Cmdstr;        /* Pointer to the command string */
  106. int Optiong;        /* Let it rip no wait for sector ACK's */
  107. int Noeofseen;
  108. int Totsecs;        /* total number of sectors this file */
  109. int Command;        /* Send a command, then exit. */
  110. int Cmdack1;        /* Rx ACKs command, then do it */
  111. int Exitcode;
  112. int Testattn;        /* Force receiver to send Attn, etc with qbf. */
  113. int Lastc;        /* Count of last buffer read or -1 */
  114. int Dontread;        /* Don't read the buffer, it's still there */
  115. int Wantfcs32;        /* want to send 32 bit FCS */
  116. long Lastread;        /* Beginning offset of last buffer read */
  117. jmp_buf intrjmp;    /* For the interrupt on RX CAN */
  118.  
  119. char *qbf;
  120. unsigned int Rxbuflen;    /* Receiver's max buffer length */
  121. int Cmdtries;
  122. int Filcnt;        /* count of number of files opened */
  123. int Lfseen;
  124. int Tframlen;        /* Override for tx frame length */
  125. int blkopt;        /* Override value for zmodem blklen */
  126. int Rxflags;
  127. int Ascii;        /* Add CR's for brain damaged programs */
  128. int Fullname;        /* transmit full pathname */
  129. int Unlinkafter;    /* Unlink file after it is sent */
  130. int Dottoslash;        /* Change foo.bar.baz to foo/bar/baz */
  131. int errcnt;        /* number of files unreadable */
  132. int siggi;        /* line interrupt enable flag     */
  133.  
  134. /* crctab calculated by Mark G. Mendel, Network Systems Corporation */
  135. unsigned int crctab[256] = {
  136.     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  137.     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  138.     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  139.     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  140.     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  141.     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  142.     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  143.     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  144.     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  145.     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  146.     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  147.     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  148.     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  149.     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  150.     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  151.     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  152.     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  153.     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  154.     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  155.     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  156.     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  157.     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  158.     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  159.     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  160.     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  161.     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  162.     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  163.     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  164.     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  165.     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  166.     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  167.     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
  168. };
  169.  
  170. /*
  171.  * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
  172.  * code or tables extracted from it, as desired without restriction.
  173.  *
  174.  *   Need an unsigned type capable of holding 32 bits;
  175.  */
  176. typedef unsigned long int UNS_32_BITS;
  177.  
  178. /* First, the polynomial itself and its table of feedback terms.  The  */
  179. /* polynomial is                                                       */
  180. /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
  181. /* Note that we take it "backwards" and put the highest-order term in  */
  182. /* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
  183. /* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
  184. /* the MSB being 1.                                                    */
  185.  
  186. /* Note that the usual hardware shift register implementation, which   */
  187. /* is what we're using (we're merely optimizing it by doing eight-bit  */
  188. /* chunks at a time) shifts bits into the lowest-order term.  In our   */
  189. /* implementation, that means shifting towards the right.  Why do we   */
  190. /* do it this way?  Because the calculated CRC must be transmitted in  */
  191. /* order from highest-order term to lowest-order term.  UARTs transmit */
  192. /* characters in order from LSB to MSB.  By storing the CRC this way,  */
  193. /* we hand it to the UART in the order low-byte to high-byte; the UART */
  194. /* sends each low-bit to hight-bit; and the result is transmission bit */
  195. /* by bit from highest- to lowest-order term without requiring any bit */
  196. /* shuffling on our part.  Reception works similarly.                  */
  197.  
  198. /* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
  199. /*                                                                     */
  200. /*     The table can be generated at runtime if desired; code to do so */
  201. /*     is shown later.  It might not be obvious, but the feedback      */
  202. /*     terms simply represent the results of eight shift/xor opera-    */
  203. /*     tions for all combinations of data and CRC register values.     */
  204. /*                                                                     */
  205. /*     The values must be right-shifted by eight bits by the "updcrc"  */
  206. /*     logic; the shift must be unsigned (bring in zeroes).  On some   */
  207. /*     hardware you could probably optimize the shift in assembler by  */
  208. /*     using byte-swap instructions.                                   */
  209.  
  210. unsigned long int crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
  211.     0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
  212.     0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 
  213.     0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
  214.     0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 
  215.     0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  216.     0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 
  217.     0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
  218.     0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 
  219.     0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
  220.     0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 
  221.     0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
  222.     0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 
  223.     0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
  224.     0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 
  225.     0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  226.     0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 
  227.     0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
  228.     0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 
  229.     0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
  230.     0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 
  231.     0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
  232.     0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 
  233.     0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
  234.     0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 
  235.     0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  236.     0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 
  237.     0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
  238.     0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 
  239.     0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
  240.     0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 
  241.     0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
  242.     0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 
  243.     0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
  244.     0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 
  245.     0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  246.     0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 
  247.     0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
  248.     0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 
  249.     0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
  250.     0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 
  251.     0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
  252.     0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 
  253.     0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
  254.     0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 
  255.     0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  256.     0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 
  257.     0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
  258.     0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 
  259.     0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
  260.     0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 
  261.     0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
  262.     0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 
  263.     0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
  264.     0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 
  265.     0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  266.     0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 
  267.     0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
  268.     0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 
  269.     0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
  270.     0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 
  271.     0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 
  272.     0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 
  273.     0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 
  274.     0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL 
  275. }; 
  276.  
  277.  
  278.         /* statics */ 
  279. static char *tsr_ptr = (char *)0x00fffa2dL; /* See St internals */
  280. static long *hz_200 =  (long *)0x000004ba; /* Yes the Hitch Hikers */
  281.                        /* Guide is wrong!! */
  282.  
  283. static long 
  284.      alrm_time = 0L,      /* Time of next timeout (200 Hz) */ 
  285.      pr_time   = 0L;      /* Present time      (200 Hz) */ 
  286.  
  287. static char *special[] = { 
  288. ".PRG", ".TOS", ".TTP", ".ARC", ".ACC", ".IMG", ".RSC", ".O",
  289. ".OBJ", ".NEO", 
  290. ".PIC", ".PI1", ".PI2", ".PI3", ".PQ1", ".PQ2", ".PQ3", ".BRD",
  291. ".ANI", ".STW", 
  292. ".FNT", ".PRT", ".SNG", ".NEC", ".CNF", ".Z"  , ".DFN", ".GEM",
  293. ".EZD", ".LNK", 
  294. ".SYM", ".DVI", ".PIX", ".X32", ".OUT", ".A",   ".CCC", ".CL",
  295. ".CMD", ".COM", 
  296. ".CRL", ".DAT", ".DIR", ".EXE", ".OVL", ".PAG", ".REL", ".SAV",
  297. ".SUB", ".SWP", 
  298. ".SYS", ".TAR", ".UTL", ".BIN", ".LBR", ".IM",  ".PAK", 
  299. "" 
  300. }; 
  301.  
  302. /* 
  303.  * mode(n) 
  304.  *  2: set a cbreak, XON/XOFF control mode if using Pro-YAM's -g
  305.  option 
  306.  *  1: save old tty stat, set raw mode  
  307.  *  0: restore original tty mode 
  308.  */
  309. mode(n)
  310. {
  311.  
  312.     vfile("mode:%d", n);
  313.     switch(n) {
  314.  
  315.     case 2:    /* Cbreak mode used by sb when -g detected */
  316.         return OK;
  317.     case 1:
  318.         return OK;
  319.     case 0:
  320.         while(Bconstat(1)) Bconin(1);    /* flush input              */
  321.  
  322.         return OK;
  323.     default:
  324.         return ERROR;
  325.     }
  326. }
  327.  
  328. /*
  329.  * send a break
  330.  * Modifies Bit 3 in the TSR (reg 23) of the Mfp
  331.  */
  332.  
  333. sendbrk()
  334. {
  335.     register long save_ssp;
  336.     register long time;
  337.  
  338.     save_ssp = Super(0L);    /* Super Mode */
  339.  
  340.     /* set bit 3 of the TSR */
  341.     *tsr_ptr |= (char)8;
  342.  
  343.     
  344.     /* wait for 250 ms */
  345.     time = *hz_200 + 50;
  346.     while(*hz_200 < time)
  347.         /* wait */ ;
  348.  
  349.     /* reset bit 3 of the tsr */
  350.     *tsr_ptr &= (char)~8;
  351.  
  352.     Super(save_ssp);    /* Back to user Mode */
  353. }
  354.  
  355. #ifdef TX
  356. /*
  357.  * Put transmit section of the MFP uart off
  358.  *
  359.  */
  360. Txoff()
  361. {
  362.     register long save_ssp;
  363.  
  364.     save_ssp = Super(0L);    /* Super Mode */
  365.     
  366.     /* clear bit 0 of the tsr */
  367.     *tsr_ptr &= (char)~1;
  368.  
  369.     Super(save_ssp);    /* Back to user Mode */
  370. }
  371.  
  372. /*
  373.  * Put transmit section of the MFP uart on
  374.  *
  375.  */
  376. Txon()
  377. {
  378.     register long save_ssp;
  379.  
  380.     save_ssp = Super(0L);    /* Super Mode */
  381.     
  382.     /* set bit 0 of the tsr */
  383.     *tsr_ptr |= (char)1;
  384.  
  385.     Super(save_ssp);    /* Back to user Mode */
  386. }
  387. #endif /* TX */
  388.  
  389.  
  390. /*
  391.  * rd_time() - read the value of the systems 200 Hz counter
  392.  * must be called in Super Mode else you get
  393.  * what you deserve - MUSHROOMS!!
  394.  */
  395. void rd_time()
  396. {
  397.     pr_time = *hz_200;
  398. }
  399.  
  400.  
  401. /*
  402.  * read_modem() - read upto count characters from the modem port
  403.  * Check for user abort (^C) and timeout at the same time
  404.  */
  405. int read_modem(buf, count)
  406. register char *buf;
  407. register int count;
  408. {
  409.     register int n;
  410.     void rd_time();
  411.  
  412.     n = 0;
  413.  
  414.     while(1)
  415.     {
  416.         if(Bconstat(2))
  417.         {
  418.             /* Character Hit at the Keyboard - is it ^C */
  419.             if((Bconin(2) & 0x7f) == CTRL('C'))
  420.             {
  421.                 /* It is a Control-C */
  422.                 if(SendType)
  423.                     bibis(3);
  424.                 else
  425.                     bibi(3);
  426.             }
  427.             
  428.         }
  429.         if(Bconstat(1))
  430.         {
  431.             /* Character available at Modem Port */
  432.             n++;
  433.             *buf++ = Bconin(1);
  434.  
  435.             while((n < count)  && Bconstat(1))
  436.             {
  437.                 *buf++ = Bconin(1);
  438.                 n++;
  439.  
  440.             }
  441.             return n;
  442.         }
  443.         
  444.         /* Check for time out if required */
  445.         if(alrm_time != 0)
  446.         {
  447.             /* Alarm Set */
  448.             Supexec(rd_time);
  449.             if(pr_time >= alrm_time)
  450.                 /* timeout */
  451.                 longjmp(tohere, -1);
  452.         }
  453.     }
  454. }
  455.  
  456.  
  457. /*
  458.  * alarm() - set the alarm time
  459.  */
  460. void stalarm(n)
  461. unsigned int n;
  462. {
  463.     void rd_time();
  464.  
  465.     if(n > 0)
  466.     {
  467.         Supexec(rd_time);
  468.         /* We really need n * 200 but n * 256 is close enough */
  469.         alrm_time = pr_time + ( n << 8 );
  470.     }
  471.     else
  472.         alrm_time = 0L;
  473. }
  474.  
  475. /*
  476.  * write_modem() - send buffer to the modem port
  477.  *
  478. */
  479. void write_modem(buf,len)
  480. register char *buf;
  481. register int len;
  482. {
  483.     register int i;
  484.     for(i = 0; i < len; i++)
  485.            Bconout(1, *buf++);
  486. }
  487.  
  488.  
  489. /*
  490.  * flushinput() - flush any characters in the modem port
  491.  * a future enhancement may be flush any characters that are in there
  492.  * and any that come in over the next 1 second -- Ymodem does that
  493.  *
  494.  */
  495. void flushinput()
  496. {
  497.     while(Bconstat(1))
  498.         Bconin(1);
  499. }
  500.  
  501.  
  502.  
  503. int isbinary(name)
  504. register char *name;
  505. {
  506.     register char **p;
  507.     register char *ext;
  508.     extern char *rindex();
  509.     extern int ustrcmp();
  510.     
  511.     if((ext = rindex(name,'.')) == (char *)NULL)
  512.     {
  513.         return 0;
  514.     }
  515.     
  516.     for(p = special; **p != '\0'; p++)
  517.         if(ustrcmp(ext,*p) == 0)
  518.         return 1;
  519.     return 0;
  520. }
  521.  
  522. #define upper(X) (islower(X)?toupper(X):X)
  523.  
  524. /* Strcmp - case insensative */
  525. int ustrcmp(s1,s2)
  526. register char *s1, *s2;
  527. {
  528.     while(*s1 != '\0')
  529.     {
  530.         if(*s2 == '\0')
  531.             return 1;
  532.         if(upper(*s1) != *s2)
  533.             return 1;
  534.         s1++;
  535.         s2++;
  536.     }
  537.     if(*s2 != '\0')
  538.         return 1;
  539.     else
  540.         return 0;
  541. }
  542.  
  543.  
  544. /*
  545.  * Ensure that each subdirectory in the pathname exists.
  546.  * If one doesn'nt, make the rest of the directory
  547.  * Returns ERROR if it has trouble creating a path
  548.  *
  549.  */
  550. int pathensure(name)
  551. char *name;
  552. {
  553.     extern char *index();
  554.  
  555.     if(index(name, '\\') == (char *)NULL)
  556.         /* nothing to check */
  557.         return OK;
  558.  
  559.     return pathrest(name, (char *)NULL);
  560. }
  561.  
  562. /*
  563.  * check rest of the path recursively
  564.  *    If any component of the path name is longer than 8/12 characters then
  565.  *    warn.
  566.  *
  567.  */
  568. int pathrest(name, prev)
  569. char *name, *prev;
  570. {
  571.     char previous[128];
  572.     char component[13];
  573.     register char *p, *q, *r, *s;
  574.     register int warn;
  575.     extern char *index();
  576.     extern char *in();
  577.  
  578.     if((r = index(name, '\\')) == (char *)NULL)
  579.         /* nothing more to check */
  580.         return OK;
  581.  
  582.     /* pick up the next component of the path name, 8/12 chars max for ST */
  583.     warn = 0;
  584.     if((s = in(name, r, '.')) == (char *)NULL)
  585.     {
  586.         /* component does'nt contain a dot */
  587.         if( ((long)r - (long)name) > 8)
  588.         {
  589.             warn++;
  590.             strncpy(component, name, 8);
  591.             q = &component[8];
  592.         }
  593.         else
  594.         {
  595.             register int n;
  596.  
  597.             n = (int)((long)r - (long)name);
  598.             strncpy(component, name, n);
  599.             component[n] = '\0';
  600.             q = &component[(strlen(component))];
  601.         }
  602.     }
  603.     else
  604.     {
  605.         /* component contains a dot */
  606.         if(((long)s - (long)name) > 8)
  607.         {
  608.             warn++;
  609.             strncpy(component, name, 8);
  610.             q = &component[8];
  611.         }
  612.         else
  613.         {
  614.             for(p = name, q = component; p != s; )
  615.                 *q++ = *p++;
  616.         }
  617.         *q++ = '.';
  618.         s++;
  619.         if(s != r)
  620.         {
  621.             if(((long)r - (long)s) > 3)
  622.             {
  623.                 warn++;
  624.                 strncpy(q, s, 3);
  625.                 q = &q[3];
  626.             }
  627.             else
  628.             {
  629.                 for(p = s; p != r; )
  630.                     *q++ = *p++;
  631.             }
  632.         }
  633.     }
  634.     *q = '\0';
  635.  
  636.     if(warn)
  637.     {
  638.         fprintf(stderr,
  639.         "?WARNING - A component of the path is longer than 8/12 chars\n");
  640.         fprintf(stderr,"%s --> %s\n", name, component);
  641.     }
  642.  
  643.     if(prev == (char *)NULL)
  644.         strcpy(previous, component);
  645.     else
  646.     {
  647.         strcpy(previous, prev);
  648.         strcat(previous, "\\");
  649.         strcat(previous, component);        
  650.     }
  651.  
  652.     if(existd(previous))
  653.         /* it exists - go do rest */
  654.         return pathrest(++r, previous);
  655.  
  656.     /* does not exist,                 */
  657.     /* make this component and all its children */
  658.     return makesubtree(++r, previous);
  659. }
  660.  
  661. /*
  662.  * make a subtree
  663.  */
  664. int makesubtree(name, prev)
  665. char *name, *prev;
  666. {
  667.     char previous[128];
  668.     char component[13];
  669.     register char *p, *q, *r, *s;
  670.     register int warn;
  671.     extern char *index();
  672.     extern char *in();
  673.  
  674.     if(Dcreate(prev) != 0)
  675.     {
  676.         log2("Trouble trying to create subtree\n");
  677.         fprintf(stderr,"%s\n", prev);
  678.         return ERROR;
  679.     }
  680.     fprintf(stderr,"Created Directory %s\n", prev);
  681.  
  682.     if((r = index(name, '\\')) == (char *)NULL)
  683.         /* nothing more to do */
  684.         return OK;
  685.  
  686.     /* pick up the next component of the path name, 8/12 chars max for ST */
  687.     warn = 0;
  688.     if((s = in(name, r, '.')) == (char *)NULL)
  689.     {
  690.         /* component does'nt contain a dot */
  691.         if( ((long)r - (long)name) > 8)
  692.         {
  693.             warn++;
  694.             strncpy(component, name, 8);
  695.             q = &component[8];
  696.         }
  697.         else
  698.         {
  699.             register int n;
  700.  
  701.             n = (int)((long)r - (long)name);
  702.             strncpy(component, name, n);
  703.             component[n] = '\0';
  704.             q = &component[(strlen(component))];
  705.         }
  706.     }
  707.     else
  708.     {
  709.         /* component contains a dot */
  710.         if(((long)s - (long)name) > 8)
  711.         {
  712.             warn++;
  713.             strncpy(component, name, 8);
  714.             q = &component[8];
  715.         }
  716.         else
  717.         {
  718.             for(p = name, q = component; p != s; )
  719.                 *q++ = *p++;
  720.         }
  721.         *q++ = '.';
  722.         s++;
  723.         if(s != r)
  724.         {
  725.             if(((long)r - (long)s) > 3)
  726.             {
  727.                 warn++;
  728.                 strncpy(q, s, 3);
  729.                 q = &q[3];
  730.             }
  731.             else
  732.             {
  733.                 for(p = s; p != r; )
  734.                     *q++ = *p++;
  735.             }
  736.         }
  737.     }
  738.     *q = '\0';
  739.  
  740.     if(warn)
  741.     {
  742.         fprintf(stderr,
  743.         "?WARNING - A component of the path is longer than 8/12 chars\n");
  744.         fprintf(stderr,"%s --> %s\n", name, component);
  745.     }
  746.  
  747.     strcpy(previous, prev);
  748.     strcat(previous, "\\");
  749.     strcat(previous, component);        
  750.  
  751.  
  752.  
  753.     /* go do the rest of them */
  754.     return makesubtree(++r, previous);
  755. }
  756.  
  757.  
  758. /*
  759.  * test if a subdirectory exists
  760.  * include special case of 'D:\' that Fsfirst does'nt handle correctly
  761.  */
  762. int existd(name)
  763. register char *name;
  764. {
  765.     /* assuming the DTA buffer is already set up */
  766.     extern long drv_map;
  767.     extern struct stat statbuf;
  768.     register int drive;
  769.     
  770.     if (Fsfirst(name , 0x0021|0x0010) == 0)
  771.     {
  772.         if((statbuf.st_mode & 0x0010) == 0x0010)
  773.             return TRUE;
  774.     }
  775.  
  776.     /* Gemdos doesn't like d:\ style dirs */
  777.     if((name[3] == '\0') && (name[2] == '\\') && (name[1] == ':'))
  778.     {
  779.         drive = name[0];
  780.         if(isupper(drive))
  781.             drive = tolower(drive);
  782.  
  783.         drive = drive - 'a';
  784.         if((drv_map & (1L << drive)) == 0)
  785.             return FALSE;
  786.         else
  787.             return TRUE;
  788.     }
  789.     /* Nor does Gemdos understand '.' or '..' */
  790.     /* Hey Atari, don't you guys ever test anything */
  791.     if((strcmp(name,".") == 0) || (strcmp(name,"..") == 0) ||
  792.        (strcmp(name,".\\") == 0) || (strcmp(name,"..\\") == 0))
  793.         return TRUE;
  794.  
  795.     return FALSE;
  796. }
  797.  
  798. /*
  799.  * Does a file exist
  800.  */
  801. int existf(name)
  802. register char *name;
  803. {
  804.     /* assuming the DTA buffer is already set up */
  805.     
  806.     return (Fsfirst(name , 0x0001) == 0);
  807.  
  808. }
  809.  
  810. /*
  811.  * stsystem(cmd) - execute a process
  812.  * char *cmd;   command to execute (including redirections etc)
  813.  */
  814. int stsystem(cmd)
  815. char *cmd;
  816. {
  817.         register char *ptr1;             /* general pointers */
  818.         register char save;              /* */
  819.         register int status;            /* return status       */
  820.         register char *args;            /* arguments            */
  821.         register int len;               /* length of args - 2   */
  822.         char nils[2];
  823.         extern char *malloc();
  824.  
  825.  
  826.         nils[0] = nils[1] = '\0';
  827.         for(ptr1 = cmd; (!isspace(*ptr1)) && (*ptr1 != '\0'); ptr1++)
  828.                 /* skip till end of path name */;
  829.         if(*ptr1 != '\0')
  830.         {
  831.                 /* cmd does have a command tail */
  832.                 /* save the char at the position and terminate the path */
  833.                 save = *ptr1;
  834.                 *ptr1++ = '\0'; /* command tail is the rest of it */
  835.  
  836.                 if((args = (char *) malloc((len = strlen(ptr1)) + 2))
  837.                     == (char *)NULL)
  838.                 {
  839.                         /* could not allocate memory */
  840.                         return(-1);
  841.                 }
  842.                 *args++ = len;
  843.                 strcpy(args,ptr1);
  844.                 args--;
  845.                 /* now do the load and go */
  846.                 status = Pexec(0,cmd,args,(char *)NULL);
  847.                 /* restore cmd to original state */
  848.                 *--ptr1 = save;
  849.                 free(args);
  850.         }
  851.         else
  852.         {
  853.                 /* command does not have a tail */
  854.  
  855.                 /* now do the load and go */
  856.                 status = Pexec(0,cmd,nils,(char *)NULL);
  857.         }
  858.  
  859.         return(status);
  860. }
  861.  
  862. stsleep(n)
  863. int n;
  864. {
  865.     void rd_time();
  866.  
  867.     if(n != 0)
  868.     {
  869.         Supexec(rd_time);
  870.         /* We really need n * 200 but n * 256 if close enough */
  871.         alrm_time = pr_time + ( n << 8 );
  872.  
  873.         while(alrm_time > pr_time)
  874.         {
  875.             Supexec(rd_time);
  876.         }
  877.         alrm_time = 0L;
  878.     }
  879. }
  880.  
  881.  
  882. initz()
  883. {
  884.      Zmodem=0;        /* ZMODEM protocol requested */
  885.      Nozmodem = 0;        /* If invoked as "rb" */
  886.      Badclose = 0;        /* Error on last close */
  887.      Batch=0;
  888.      Wcsmask=0377;
  889.      Verbose=0;
  890.      lsct = 1;
  891.      Quiet=0;        /* overrides logic that would otherwise set verbose */
  892.      Lleft=0;        /* number of characters in linbuf */
  893.  
  894.      logf = (FILE *)NULL;
  895.      vdebug = 0;
  896.  
  897.      Readnum = KSIZE;    /* Number of bytes to ask for in read() from modem */
  898.      Crcflg = FALSE;
  899.      fout = (-1);
  900.      errors = 0;
  901.      Rxtimeout = 100;    /* Tenths of seconds to wait for something */
  902.      Modem = 0;
  903.      Blklen = SECSIZ;    /* record length of received packets */
  904.  
  905.     qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
  906.     Cmdtries = 11;
  907.     Filcnt=0;        /* count of number of files opened */
  908.     Lfseen=0;
  909.     Rxbuflen = 1024;    /* Receiver's max buffer length */
  910.     Tframlen = 0;        /* Override for tx frame length */
  911.     blkopt=0;        /* Override value for zmodem blklen */
  912.     Rxflags = 0;
  913.     Ascii=0;        /* Add CR's for brain damaged programs */
  914.     Fullname=0;        /* transmit full pathname */
  915.     Unlinkafter=0;        /* Unlink file after it is sent */
  916.     Dottoslash=0;        /* Change foo.bar.baz to foo/bar/baz */
  917.     errcnt=0;        /* number of files unreadable */
  918.     Testattn = FALSE;
  919.     siggi = 0;
  920.     Command = FALSE;
  921.     Wantfcs32 = TRUE;    /* want to send 32 bit FCS */
  922.     Znulls = 0;
  923.     tryzhdrtype=ZRINIT;    /* Header type to send corresponding to Last rx close */
  924.     Txfcs32 = FALSE;    /* TRUE means send binary frames with 32 bit FCS */
  925.     ForceBinary = FALSE;    /* Local force binary override for rz */
  926.      
  927. }
  928.  
  929. /* abort current session - due to async fault */
  930. aexit(n)
  931. int n;
  932. {
  933.     longjmp(abrtjmp, n);
  934. }
  935.  
  936. buserr()
  937. {
  938.     longjmp(busjmp, -1);
  939. }
  940.  
  941. addrerr()
  942. {
  943.     longjmp(addrjmp, -1);
  944. }
  945.  
  946. /*
  947.  * Local console output simulation
  948.  */
  949. bttyout(c)
  950. {
  951.     if (Verbose)
  952.         putc(c, stderr);
  953. }
  954.  
  955. /*
  956.  *  Send a character to modem.  Small is beautiful.
  957.  */
  958. sendline(c)
  959. int c;
  960. {
  961.     if (Verbose>4)
  962.     {
  963.         fprintf(stderr, "Sendline: %x\n", c);
  964.  
  965.     }
  966.     if (SendType)
  967.         Bconout(1, c & Wcsmask);
  968.     else
  969.         Bconout(1, c);
  970.  
  971. }
  972.  
  973.  
  974.  
  975. /*
  976.  * substr(string, token) searches for token in string s
  977.  * returns pointer to token within string if found, NULL otherwise
  978.  */
  979. char *
  980. substr(s, t)
  981. register char *s;
  982. char *t;
  983. {
  984.     register char *ss,*tt;
  985.     /* search for first char of token */
  986.     for (ss=s; *s; s++)
  987.         if (*s == *t)
  988.             /* compare token with substring */
  989.             for (ss=s,tt=t; ;)
  990.             {
  991.                 if (*tt == '\0')
  992.                     return s;
  993.                 if (*ss++ != *tt++)
  994.                     break;
  995.             }
  996.  
  997.     return ((char *)NULL);
  998. }
  999.  
  1000.  
  1001. /* send cancel string to get the other end to shut up */
  1002. canit()
  1003. {
  1004.     static char canistr[] = {
  1005.      ZPAD,ZPAD,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  1006.     };
  1007.  
  1008.     write_modem(canistr, strlen(canistr));
  1009.     if(!SendType)
  1010.         Lleft=0;    /* Do read next time ... */
  1011.  
  1012. }
  1013.  
  1014.  
  1015. /*
  1016.  *  Debugging information output interface routine
  1017.  */
  1018. /* VARARGS1 */
  1019. vfile(f, a, b, c)
  1020. register char *f;
  1021. int a, b, c;
  1022. {
  1023.     if (Verbose > 3)
  1024.     {    /* verbose 2 is normal for us */
  1025.         fprintf(stderr, f, a, b, c);
  1026.         fprintf(stderr, "\n");
  1027.  
  1028.         if(vdebug && (logf != (FILE *)NULL))
  1029.         {
  1030.             fprintf(logf, f, a, b, c);
  1031.             fprintf(logf, "\n");
  1032.             fflush(logf);
  1033.         }
  1034.  
  1035.     }
  1036. }
  1037.  
  1038. /* longs and pointers are not integers */
  1039. /* VARARGS1 */
  1040. vfile2(f, a, b, c)
  1041. long a, b, c;
  1042. register char *f;
  1043. {
  1044.     if (Verbose > 3)
  1045.     {
  1046.         fprintf(stderr, f, a, b, c);
  1047.         fprintf(stderr, "\n");
  1048.  
  1049.         if(vdebug && (logf != (FILE *)NULL))
  1050.         {
  1051.             fprintf(logf, f, a, b, c);
  1052.             fprintf(logf, "\n");
  1053.             fflush(logf);
  1054.         }
  1055.  
  1056.     }
  1057. }
  1058.  
  1059. char *in(from, to, c)
  1060. register char *from, *to;
  1061. register int c;
  1062. {
  1063.     for(; from < to; from++)
  1064.     {
  1065.         if(*from == c)
  1066.             return from;
  1067.     }
  1068.     return (char *)NULL;
  1069. }
  1070.  
  1071. /** EOF **/
  1072.